<!doctype html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta name="description" content="coinfaces">

        <title>记录Django 请求和响应日志</title>

    <link rel="stylesheet" href="../theme/css/style.css">
    <link rel="stylesheet" href="../theme/css/pygments.css">



</head>

<body>
    <div class="content">
<h1>记录Django 请求和响应日志</h1>    <p>
        under
            <a href="../tags/django/">Django</a>
    </p>
    <p>
        in <a href="../categories/uncategorized/">Uncategorized</a>
    </p>
    <p>Published: 2019-04-16</p>


    <!-- wp:paragraph -->

<p>在调试
<a href="https://github.com/ottoyiu/django-cors-headers">django-cors-headers</a>
设置的时候，想要看到传给中间件（corsheaders.middleware.CorsMiddleware）的请求头和从中间件返回的响应头是什么样的。</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->

<p>一开始使用了 corsheaders.signals.check_request_enabled
信号的处理函数，在处理函数中记录请求头，具体操作见 <a href="https://github.com/ottoyiu/django-cors-headers#signals">django-cors-headers
提供的示例</a>，这里把
cors_allow_mysites 函数替换成了记录日志的函数：</p>
<!-- /wp:paragraph -->

<!-- wp:code -->

<div class="highlight"><pre><span></span><code><span class="kn">import</span> <span class="nn">logging</span>

<span class="k">def</span> <span class="nf">log_request_headers</span><span class="p">(</span><span class="n">sender</span><span class="p">,</span> <span class="n">request</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>
    <span class="n">logger</span> <span class="o">=</span> <span class="n">logging</span><span class="o">.</span><span class="n">getLogger</span><span class="p">(</span><span class="s1">&#39;django&#39;</span><span class="p">)</span>
    <span class="n">logger</span><span class="o">.</span><span class="n">info</span><span class="p">(</span><span class="s1">&#39;Request headers: {}&#39;</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">request</span><span class="o">.</span><span class="n">headers</span><span class="p">))</span>
</code></pre></div>


<!-- /wp:code -->

<!-- wp:list -->

<ul>
<li>这种方法有明显的缺陷，该日志记录函数的执行依赖于 django-cors-headers
    的执行，即只有 django-cors-headers 认为该请求无法通过 CORS
    筛选的时候，才会执行这个函数。</li>
<li>这个函数的执行存在风险，因为它会影响中间件是否允许该请求的跨域访问的判断，如果这个函数返回
    True，则通过 CORS 筛选，虽然这里它返回 None
    不会对结果造成影响，但很难预测 django-cors-headers
    版本升级后会引起什么后果。</li>
<li>这个函数无法记录中间件返回的响应是什么。</li>
</ul>
<!-- /wp:list -->

<!-- wp:paragraph -->

<p>理想的解决方案是实现自己的中间件，在应用目录下创建
middleware.py，其内容如下：</p>
<!-- /wp:paragraph -->

<!-- wp:code -->

<div class="highlight"><pre><span></span><code><span class="kn">import</span> <span class="nn">logging</span>


<span class="k">def</span> <span class="nf">log_headers</span><span class="p">(</span><span class="n">get_response</span><span class="p">):</span>
    <span class="n">logger</span> <span class="o">=</span> <span class="n">logging</span><span class="o">.</span><span class="n">getLogger</span><span class="p">(</span><span class="s1">&#39;django&#39;</span><span class="p">)</span>

    <span class="k">def</span> <span class="nf">middleware</span><span class="p">(</span><span class="n">request</span><span class="p">):</span>
        <span class="n">nonlocal</span> <span class="n">logger</span>

        <span class="n">logger</span><span class="o">.</span><span class="n">info</span><span class="p">(</span><span class="s1">&#39;Pre request headers: {0!s}&#39;</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">request</span><span class="o">.</span><span class="n">headers</span><span class="p">))</span>

        <span class="n">response</span> <span class="o">=</span> <span class="n">get_response</span><span class="p">(</span><span class="n">request</span><span class="p">)</span>

        <span class="n">logger</span><span class="o">.</span><span class="n">info</span><span class="p">(</span><span class="s1">&#39;Response headers: {0!s}&#39;</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">response</span><span class="o">.</span><span class="n">_headers</span><span class="p">))</span>

        <span class="k">return</span> <span class="n">response</span>

    <span class="k">return</span> <span class="n">middleware</span>
</code></pre></div>


<!-- /wp:code -->

<!-- wp:paragraph -->

<p>然后把这个中间件加到中间件（corsheaders.middleware.CorsMiddleware）的前面，就可以记录中间件得到的
request 和中间件返回的 response 的消息头了。</p>
<!-- /wp:paragraph -->

<!-- wp:code -->

<div class="highlight"><pre><span></span><code><span class="err">MIDDLEWARE = [</span>
<span class="err">    ...</span>
<span class="err">    &#39;myapp.middleware.log_headers&#39;,</span>
<span class="err">    &#39;corsheaders.middleware.CorsMiddleware&#39;,</span>
<span class="err">    ...</span>
<span class="err">]</span>
</code></pre></div>


<!-- /wp:code -->
    </div>
<nav class="nav sidebar">
    <div class="siteinfo">
        <div class="sitename"><a href="..">coinfaces</a></div>
        <div class="tagline">Another Side of Life</div>
    </div>

        <a href="../categories/">categories</a>
        <a href="..">&larr; Home</a>
</nav><footer class="footer">
    <span>
        &copy; jpli &middot;
        under <a rel="license" href="http://creativecommons.org/licenses/by-sa/4.0/">CC-BY-SA 4.0</a>
    </span>
    |
    <span>
        Powered by:
        <a href="http://blog.getpelican.com/">Pelican</a>
    </span>
</footer></body>
</html>